plat: marvell: sip: make sure that comphy init will use correct address
authorGrzegorz Jaszczyk <[email protected]>
Thu, 4 Apr 2019 15:16:39 +0000 (17:16 +0200)
committerGrzegorz Jaszczyk <[email protected]>
Fri, 5 Apr 2019 10:48:40 +0000 (12:48 +0200)
The argument passed via x1 is used as a base address for comphy related
routines. Nevertheless validation of this address wasn't good enough and
allowed some non comphy related addresses to slip over.

To overcome this issue make sure that the address passed via SMC points
to valid CP range and allow to proceed comphy initializations only with
correct comphy offset.

This could be fixed in a different way e.g. by passing CP id from the
caller, but since this API is already used with various Linux, U-Boot
and UEFI versions it can't be changed.

Signed-off-by: Grzegorz Jaszczyk <[email protected]>
Change-Id: Ia74dbc36efcfbefc4a102d31191e6af5808c4a82

plat/marvell/common/mrvl_sip_svc.c

index df211059b9d692b19f964fa0ff4c7bfd9212ffed..36cada193f2bd9c671acc66773c4dc40fbd7c00b 100644 (file)
@@ -15,6 +15,7 @@
 #include <plat_marvell.h>
 
 #include "comphy/phy-comphy-cp110.h"
+#include <stdbool.h>
 
 /* #define DEBUG_COMPHY */
 #ifdef DEBUG_COMPHY
 
 #define MAX_LANE_NR            6
 #define MVEBU_COMPHY_OFFSET    0x441000
-#define MVEBU_SD_OFFSET                0x120000
+#define MVEBU_CP_BASE_MASK     (~0xffffff)
 
 /* This macro is used to identify COMPHY related calls from SMC function ID */
 #define is_comphy_fid(fid)     \
        ((fid) >= MV_SIP_COMPHY_POWER_ON && (fid) <= MV_SIP_COMPHY_DIG_RESET)
 
+_Bool is_cp_range_valid(u_register_t *addr)
+{
+       int cp_nr;
+
+       *addr &= MVEBU_CP_BASE_MASK;
+       for (cp_nr = 0; cp_nr < CP_NUM; cp_nr++) {
+               if (*addr == MVEBU_CP_REGS_BASE(cp_nr))
+                       return true;
+       }
+
+       return false;
+}
 
 uintptr_t mrvl_sip_smc_handler(uint32_t smc_fid,
                               u_register_t x1,
@@ -59,20 +72,17 @@ uintptr_t mrvl_sip_smc_handler(uint32_t smc_fid,
 
        debug("%s: got SMC (0x%x) x1 0x%lx, x2 0x%lx, x3 0x%lx\n",
                                                 __func__, smc_fid, x1, x2, x3);
-       if (is_comphy_fid(smc_fid)) {
-
-               /* some systems passes SD phys address instead of COMPHY phys
-                * address - convert it
-                */
-               if (x1 & MVEBU_SD_OFFSET)
-                       x1 = (x1 & ~0xffffff) + MVEBU_COMPHY_OFFSET;
 
-               if ((x1 & 0xffffff) != MVEBU_COMPHY_OFFSET) {
+       if (is_comphy_fid(smc_fid)) {
+               /* validate address passed via x1 */
+               if (!is_cp_range_valid(&x1)) {
                        ERROR("%s: Wrong smc (0x%x) address: %lx\n",
                              __func__, smc_fid, x1);
                        SMC_RET1(handle, SMC_UNK);
                }
 
+               x1 += MVEBU_COMPHY_OFFSET;
+
                if (x2 >= MAX_LANE_NR) {
                        ERROR("%s: Wrong smc (0x%x) lane nr: %lx\n",
                              __func__, smc_fid, x2);